/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import camera from '@ohos.multimedia.camera'
import Logger from '../common/Logger'

export default class CameraService {
    private tag: string = 'CameraService'
    private context: any = undefined
    private cameraManager: camera.CameraManager = undefined
    private cameras: Array<camera.CameraDevice> = undefined
    private cameraInput: camera.CameraInput = undefined
    private previewOutput: camera.PreviewOutput = undefined
    private cameraOutputCapability: camera.CameraOutputCapability = undefined
    private captureSession: camera.CaptureSession = undefined

    constructor(context: any) {
        this.context = context
    }

    async hasLocalCamera(): Promise<boolean> {
        Logger.info(this.tag, 'hasLocalCamera')
        this.cameraManager = camera.getCameraManager(this.context)
        Logger.info(this.tag, 'hasLocalCamera getCameraManager success')

        try {
            this.cameras = this.cameraManager.getSupportedCameras()
            Logger.info(this.tag, `hasLocalCamera getSupportedCameras len:${this.cameras.length}`)
        } catch (err) {
            Logger.info(this.tag, 'hasLocalCamera getSupportedCameras failed')
            return false
        }
        if (this.cameras) {
            for (let cameraIndex = 0; cameraIndex < this.cameras.length; cameraIndex++) {
                Logger.info(this.tag, `hasLocalCamera cameraIndex:${cameraIndex}`)
                Logger.info(this.tag, `hasLocalCamera connectionType:${this.cameras[cameraIndex].connectionType}`)
                if (this.cameras[cameraIndex].connectionType != camera.ConnectionType.CAMERA_CONNECTION_REMOTE) {
                    return true
                }
            }
        }
        return false
    }

    async initCamera(surfaceId: string) {
//        Logger.info(this.tag, 'initCamera')
        await this.releaseCamera()

        this.cameraManager = camera.getCameraManager(this.context)
//        Logger.info(this.tag, 'getCameraManager success')

        this.cameras = this.cameraManager.getSupportedCameras()
        let localCamera: camera.CameraDevice

        if (this.cameras) {
            Logger.info(this.tag, `get cameras success: ${this.cameras.length}`)
            for (let cameraIndex = 0; cameraIndex < this.cameras.length; cameraIndex++) {
                Logger.info(this.tag, 'cameraId : ' + this.cameras[cameraIndex].cameraId) // 获取相机ID
                Logger.info(this.tag, 'cameraPosition : ' + this.cameras[cameraIndex].cameraPosition) // 获取相机位置
                Logger.info(this.tag, 'cameraType : ' + this.cameras[cameraIndex].cameraType) // 获取相机类型
                Logger.info(this.tag, 'connectionType : ' + this.cameras[cameraIndex].connectionType) // 获取相机连接类型
                if (this.cameras[cameraIndex].connectionType != camera.ConnectionType.CAMERA_CONNECTION_REMOTE) {
                    localCamera = this.cameras[cameraIndex]
                    break;
                }
            }
        } else {
            Logger.error(this.tag, `get cameras failed!`)
            return
        }
        Logger.info(this.tag, `localCamera cameraId:${localCamera.cameraId}`)
        if(localCamera.cameraId){
            this.cameraInput = this.cameraManager.createCameraInput(localCamera)
//            Logger.info(this.tag, 'createCameraInput')
            await this.cameraInput.open()
//            Logger.info(this.tag, 'open')

            this.cameraOutputCapability = this.cameraManager.getSupportedOutputCapability(localCamera)
            let previewProfiles: Array<camera.Profile> = this.cameraOutputCapability.previewProfiles;
            let previewProfile: camera.Profile
            let previewCapLen = previewProfiles.length;
            Logger.info(this.tag, 'previewCapLen:' + previewCapLen);

            for (let capIndex = previewCapLen - 1; capIndex >= 0; capIndex--) {
                let item = previewProfiles[capIndex];
                // 取 argb 预览
                Logger.info(this.tag, 'previewProfile format:' + item.format);
                Logger.info(this.tag, 'select previewProfile.width: ' + item.size.width)
                Logger.info(this.tag, 'select previewProfile.height: ' + item.size.height)

                // 不同的摄像头的属性选择不一样，需要按实际设备进行调试

//                if (item.format === 1003 && item.size.width === 1920 && item.size.height === 1080) {
//                    previewProfile = item;
//                    break;
//                }
                if (item.format === 3 && item.size.width === 1920 && item.size.height === 1080) {
                    previewProfile = item;
//                    break;
                }
            }
//            Logger.info(this.tag, 'surfaceId:'+surfaceId)
            this.previewOutput = this.cameraManager.createPreviewOutput(previewProfile, surfaceId)
//            Logger.info(this.tag, 'createPreviewOutput')
            this.captureSession = this.cameraManager.createCaptureSession()
//            Logger.info(this.tag, 'createCaptureSession')
            this.captureSession.beginConfig()
//            Logger.info(this.tag, 'beginConfig')
            this.captureSession.addInput(this.cameraInput)
//            Logger.info(this.tag, 'addInput')
            this.captureSession.addOutput(this.previewOutput)
//            Logger.info(this.tag, 'addOutput')
            await this.captureSession.commitConfig()
//            Logger.info(this.tag, 'commitConfig')
            await this.captureSession.start()
//            Logger.info(this.tag, 'captureSession start')
        }
    }

    async releaseCamera() {
        Logger.info(this.tag, 'releaseCamera')
        if (this.cameraInput) {
            await this.cameraInput.close()
        }
        if (this.previewOutput) {
            await this.previewOutput.release()
        }
        if (this.captureSession) {
            await this.captureSession.release()
        }
    }
}